/*
 * main.cpp
 *
 *  Created on: Oct 24, 2012
 *      Author: Bhupendra Aole
 */

#include <iostream>
#include <string>
#include "tinyxml/tinyxml.h"
#include "util.h"
#include "GameFlow.h"
#include "DXEngine.h"

using namespace std;

//--------------------------------------------------------------------------------------
// Global Variables
//--------------------------------------------------------------------------------------
HINSTANCE g_hInst = NULL;

aole::DXEngine engine;
GameFlow gameFlow;

//--------------------------------------------------------------------------------------
// Forward declarations
//--------------------------------------------------------------------------------------
void processFlow( const char* pFilename );
HWND InitWindow( HINSTANCE hInstance, int nCmdShow );
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );

int wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine,
		int nCmdShow ) {

	HWND hWnd = InitWindow( hInstance, nCmdShow );
	if ( !hWnd )
		return 2;

	if ( FAILED( engine.InitDevice(hWnd) )) {
		engine.CleanupDevice();
		return 3;
	}

	processFlow( "flow.xml" );

	// Main message loop
	MSG msg = { 0 };
	while ( WM_QUIT != msg.message ) {
		if ( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) ) {
			TranslateMessage( &msg );
			DispatchMessage( &msg );
		} else {
			engine.renderBegin();
			gameFlow.render(&engine);
			engine.renderEnd();
		}
	}

	engine.CleanupDevice();

	return (int) msg.wParam;
}

void processFlow( const char* pFilename ) {
	TiXmlDocument doc( pFilename );
	bool loadOkay = doc.LoadFile();

	if ( loadOkay ) {
		//processFlow( &doc );
	} else {
		cout << "Error in loading Game Flow file: " << pFilename;
		return;
	}

	TiXmlNode* eVisq = doc.FirstChild();
	// get visq element
	if ( !UTIL::isNode( "visq", eVisq ) ) {
		cout << "Error in getting 'visq' element in file: " << pFilename;
		return;
	}
	// TODO: check for visq version

	// get scenes element
	TiXmlNode* eScenes = eVisq->FirstChild();
	if ( !UTIL::isNode( "scenes", eScenes ) ) {
		cout << "Error in getting 'scenes' element in file: " << pFilename;
		return;
	}

	// get each scene
	for ( TiXmlNode* eScene = eScenes->FirstChild(); eScene != 0; eScene =
			eScene->NextSibling() ) {
		string id;

		if ( !UTIL::getAttribute( eScene->ToElement(), "id", &id ) ) {
			cout << "Scene id not found.\n";
			return;
		}
		gameFlow.createScene( id );
	}

	// get default scene
	TiXmlNode* eStart = eScenes->NextSibling();
	if ( !UTIL::isNode( "start", eStart ) ) {
		cout << "Error in getting 'start' element in file: " << pFilename;
		return;
	}
	string startScene;
	if ( !UTIL::getAttribute( eStart->ToElement(), "scene", &startScene ) ) {
		cout << "Scene id not found.\n";
		return;
	}
	gameFlow.setStartingScene( startScene );

	gameFlow.start( &engine );
}

//--------------------------------------------------------------------------------------
// Register class and create window
//--------------------------------------------------------------------------------------
HWND InitWindow( HINSTANCE hInstance, int nCmdShow ) {
	HWND hWnd = NULL;
	// Register class
	WNDCLASSEX wcex;
	wcex.cbSize = sizeof(WNDCLASSEX);
	wcex.style = CS_HREDRAW | CS_VREDRAW;
	wcex.lpfnWndProc = WndProc;
	wcex.cbClsExtra = 0;
	wcex.cbWndExtra = 0;
	wcex.hInstance = hInstance;
	wcex.hIcon = LoadIcon( hInstance, (LPCTSTR) IDI_APPLICATION );
	wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
	wcex.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
	wcex.lpszMenuName = NULL;
	wcex.lpszClassName = L"VisqWindowClass";
	wcex.hIconSm = LoadIcon( wcex.hInstance, (LPCTSTR) IDI_APPLICATION );
	if ( !RegisterClassEx( &wcex ) )
		return 0;

	// Create window
	g_hInst = hInstance;
	RECT rc = { 0, 0, 640, 480 };
	AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
	hWnd =
			CreateWindow( L"VisqWindowClass", L"Vision Quest Game Editor", WS_OVERLAPPEDWINDOW,
					CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance,
					NULL );
	if ( !hWnd )
		return 0;

	ShowWindow( hWnd, nCmdShow );

	return hWnd;
}

//--------------------------------------------------------------------------------------
// Called every time the application receives a message
//--------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam,
		LPARAM lParam ) {
	PAINTSTRUCT ps;
	HDC hdc;

	switch ( message ) {
	case WM_PAINT:
		hdc = BeginPaint( hWnd, &ps );
		EndPaint( hWnd, &ps );
		break;

	case WM_DESTROY:
		PostQuitMessage( 0 );
		break;

	default:
		return DefWindowProc( hWnd, message, wParam, lParam );
	}

	return 0;
}
